from abc import ABC, abstractmethod
from typing import List


class Animal(ABC):
    """
    动物抽象基类，定义了所有动物共有的属性和方法。

    属性:
        name (str): 动物的名字
        age (int): 动物的年龄
    """

    def __init__(self, name: str, age: int = 0):
        """
        初始化动物对象。

        参数:
            name (str): 动物的名字
            age (int, optional): 动物的年龄，默认为0
        """
        if not name or not isinstance(name, str):
            raise ValueError("名字必须是非空字符串")
        if age < 0 or not isinstance(age, int):
            raise ValueError("年龄必须是非负整数")

        self.name = name
        self.age = age

    @abstractmethod
    def speak(self) -> str:
        """
        动物发出声音的抽象方法。

        返回:
            str: 动物发出的声音描述
        """
        pass

    def move(self) -> str:
        """
        动物移动的方法。

        返回:
            str: 动物移动的描述
        """
        return f"{self.name} is moving."

    def eat(self, food: str) -> str:
        """
        动物进食的方法。

        参数:
            food (str): 食物的名称

        返回:
            str: 动物进食的描述
        """
        return f"{self.name} is eating {food}."

    def __str__(self) -> str:
        """
        返回动物的字符串表示。

        返回:
            str: 动物的描述
        """
        return (f"{self.__class__.__name__} named {self.name}, "
                f"{self.age} years old")


class Dog(Animal):
    """
    狗类，继承自Animal类。
    """

    def __init__(self, name: str, age: int = 0, breed: str = "Unknown"):
        """
        初始化狗对象。

        参数:
            name (str): 狗的名字
            age (int, optional): 狗的年龄，默认为0
            breed (str, optional): 狗的品种，默认为"Unknown"
        """
        super().__init__(name, age)
        self.breed = breed

    def speak(self) -> str:
        """
        狗发出声音的方法。

        返回:
            str: 狗发出的声音描述
        """
        return f"{self.name} says Woof!"

    def fetch(self, item: str) -> str:
        """
        狗接飞盘的方法。

        参数:
            item (str): 要接的物品名称

        返回:
            str: 狗接物品的描述
        """
        return f"{self.name} is fetching the {item}."


class Cat(Animal):
    """
    猫类，继承自Animal类。
    """

    def __init__(self, name: str, age: int = 0, color: str = "Unknown"):
        """
        初始化猫对象。

        参数:
            name (str): 猫的名字
            age (int, optional): 猫的年龄，默认为0
            color (str, optional): 猫的颜色，默认为"Unknown"
        """
        super().__init__(name, age)
        self.color = color

    def speak(self) -> str:
        """
        猫发出声音的方法。

        返回:
            str: 猫发出的声音描述
        """
        return f"{self.name} says Meow!"

    def climb(self, height: int) -> str:
        """
        猫爬高的方法。

        参数:
            height (int): 爬高的高度（米）

        返回:
            str: 猫爬高的描述
        """
        return f"{self.name} is climbing {height} meters high."


def animal_sound(animals: List[Animal]) -> None:
    """
    让所有动物发出声音的函数。

    参数:
        animals (List[Animal]): 动物列表
    """
    for animal in animals:
        print(animal.speak())


# 示例用法
if __name__ == "__main__":
    # 创建动物对象
    dog = Dog("Buddy", 3, "Golden Retriever")
    cat = Cat("Whiskers", 2, "Orange")

    # 让动物发出声音
    animals = [dog, cat]
    animal_sound(animals)

    # 展示其他功能
    print(dog.move())
    print(dog.eat("bone"))
    print(dog.fetch("ball"))
    print(cat.climb(2))

    # 展示字符串表示
    print(dog)
    print(cat)
